"""
1.
绘制不同组数
误差线 验证集准确率、测试集准确率、精确率、召回率、F1分数
绘制 faiss的误差线

2.
绘制单独CNN 和 CNN+faiss联用的比较

"""

import pandas as pd
import json
import numpy as np
import matplotlib.pyplot as plt

colors = ["#A1A9D0","#F0988C","#B883D4","#CFEAF1"]

dark_green = '#006400'  # 深绿色，十六进制颜色代码
light_green = '#90EE90'  # 浅绿色，十六进制颜色代码
# 定义相似色系的颜色
blue_palette = ['#ADD8E6', '#87CEEB', '#00008B', '#006994']
green_palette = ['#90EE90', '#808000', '#228B22', '#006400']
red_palette = ['#FFB6C1', '#FFA07A', '#FF0000', '#8B0000']

# 获取数据
def process_data(pth = r"D:\Code\CNN识别菌种\RunningData\RunDataTemp.xlsx"):
    df = pd.read_excel(pth)
    epo_list = [5,10,20,40]
    ret = pd.DataFrame({"Epoch Count":epo_list})
    ret1 = pd.DataFrame({"Name":["CNN","CNN+faiss"]})
    dt = {}

    # 处理轮次数据
    for e in epo_list:
        temp = df.loc[df["Epoch Count"] == e]
        dt[e] = [temp["Last Train Accuracy"].mean(),temp["Last Train Accuracy"].std(),temp["Test Accuracy"].mean(),temp["Test Accuracy"].std(),temp["Test Precison"].mean(),temp["Test Precison"].std(),temp["Test Recall"].mean(),temp["Test Recall"].std(),temp["Test F1 Grades"].mean(),temp["Test F1 Grades"].std()]
    ret["Test Mean"] = [dt[5][2],dt[10][2],dt[20][2],dt[40][2]]
    ret["Test Std"] = [dt[5][3],dt[10][3],dt[20][3],dt[40][3]]
    ret["Pre Mean"] = [dt[5][4], dt[10][4], dt[20][4], dt[40][4]]
    ret["Pre Std"] = [dt[5][5], dt[10][5], dt[20][5], dt[40][5]]
    ret["Rec Mean"] = [dt[5][6], dt[10][6], dt[20][6], dt[40][6]]
    ret["Rec Std"] = [dt[5][7], dt[10][7], dt[20][7], dt[40][7]]
    ret["F1 Mean"] = [dt[5][8], dt[10][8], dt[20][8], dt[40][8]]
    ret["F1 Std"] = [dt[5][9], dt[10][9], dt[20][9], dt[40][9]]

    # 处理 faiss数据
    with open('RunningData\\faiss.json', 'r') as f:
        acc_list = json.load(f)
        acc_list.pop()
        temp = pd.DataFrame({"acc":acc_list})

    ret1["Mean"] = [dt[20][2],temp["acc"].mean()]
    ret1["Std"] = [dt[20][3],temp["acc"].std()]

    return ret,ret1
# 绘制误差线
def draw_error_bar():
    diff_ep,diff_kd = process_data()

    # 绘制CNN和faiss的误差线
    fig = plt.figure(figsize = (12.8,10))
    index = np.arange(2) * 0.7
    plt.bar(index,diff_kd["Mean"],width=0.4,yerr=diff_kd["Std"],error_kw = {'ecolor' : '0.2', 'capsize' :6 },color = colors[0:2])
    plt.xticks(index, ["CNN","CNN+Faiss"], fontsize=24)  # 设置横坐标刻度
    plt.yticks(fontsize=24)  ##设置纵坐标刻度大小
    plt.ylim(0, 1.00)  # 设置纵坐标轴范围
    plt.xlabel("Classification", fontsize=24)  # 设置横坐标轴名称
    plt.ylabel("Accuracy", fontsize=24)  # 设置纵坐标轴名称
    plt.title('Error bar for different ways', fontsize=24)  # 设置标题名称
    plt.savefig("CNN and Faiss.png")


    # 绘制不同组次的误差线
    fig = plt.figure(figsize = (19.2,12.8))
    width = 0.05
    space = 0.05*1.24
    index = np.arange(4) * 0.3
    plt.bar(index,diff_ep["Test Mean"],width=width,yerr=diff_ep["Test Std"],error_kw = {'ecolor' : '0.2', 'capsize' :6 },label = "Accuracy",color = colors[0])
    plt.bar([i + space for i in index],diff_ep["Pre Mean"],width=width,yerr=diff_ep["Pre Std"],error_kw = {'ecolor' : '0.2', 'capsize' :6 },label = "Precision",color=colors[1])
    plt.bar([i + 2*space for i in index],diff_ep["Rec Mean"],width=width,yerr=diff_ep["Rec Std"],error_kw = {'ecolor' : '0.2', 'capsize' :6 },label = "Recall",color = colors[2])
    plt.bar([i + 3*space for i in index],diff_ep["F1 Mean"],width=width,yerr=diff_ep["F1 Std"],error_kw = {'ecolor' : '0.2', 'capsize' :6 },label = "F1",color = colors[3])
    plt.xticks(index+0.085,[5,10,20,40], fontsize=24)  # 设置横坐标刻度
    plt.yticks(fontsize=24)  ##设置纵坐标刻度大小
    plt.ylim(0, 1.00)  # 设置纵坐标轴范围
    plt.xlabel("Epoch", fontsize=24)  # 设置横坐标轴名称
    plt.ylabel("Accuracy", fontsize=24)  # 设置纵坐标轴名称
    plt.title('Error bar for different epoch', fontsize=24)  # 设置标题名称
    # 显示图例
    plt.legend(loc='lower right',fontsize=16)
    plt.savefig("Error bar.png")

draw_error_bar()